package com.qwt.server.utils;

import com.qwt.server.advice.FException;
import com.qwt.server.bean.FileMetaBo;
import com.qwt.server.bean.FileResTo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.sql.Date;
import java.time.Instant;
import java.util.Objects;

/**
 * @author 时光
 * @date 2021/12/10 13:0340
 */
@Slf4j
public class FileUtil {
    public static String BASE_PATH;

    static {
        try {
            BASE_PATH = ResourceUtils.getURL("classpath:").getPath();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     * 相对地址前缀
     */
    public static final String RELATIVE_PATH_PRIEFIX = "static/upload" + File.separatorChar;

    /**
     * 生成相对地址
     * @param sufix 子级地址
     * @return 相对地址
     */
    public static String generateRelativePath(String sufix){
        return RELATIVE_PATH_PRIEFIX+sufix.replaceAll("^[\\s/\\\\]*|[\\s/\\\\]*$","")
                    .replaceAll("/+|\\\\+",File.separatorChar+"")
                +File.separatorChar;
    }

    /**
     * 生成相对地址-默认日期做子级路径
     * @return 相对地址
     */
    public static String generateRelativePath(){
        return generateRelativePath(DateUtil.formatWithoutDelimiter(Date.from(Instant.now())));
    }

    /**
     * 生成类绝对地址路径-默认日期做子级路径
     * @return 绝对地址
     */
    public static String generateAbsPathWithClassPath(){
        return BASE_PATH+generateRelativePath();
    }

    /**
     * 生成类绝对地址路径
     * @param sufix 子级地址
     * @return 绝对地址
     */
    public static String generateAbsPathWithClassPath(String sufix){
        return BASE_PATH+generateRelativePath(sufix);
    }

    /**
     * 上传单个文件
     * @param multipartFile 文件流
     * @return To模型
     */
    public static FileResTo uploadFile(MultipartFile multipartFile){
        if (multipartFile ==null || multipartFile.isEmpty()){
            throw FException.of("请选择文件",501);
        }
        FileMetaBo fileMetaBo = readFileToEntity(multipartFile);
        File file = new File(fileMetaBo.getSavePath());
        if (!file.getParentFile().exists()){
            boolean ifMkSuccess = file.getParentFile().mkdirs();
            log.info("本地文件夹:[{}]不存在需要立即创建, 结果: {}",file.getParentFile().getAbsolutePath(),ifMkSuccess);
        }
        try {
            multipartFile.transferTo(file);
            return FileResTo.of(fileMetaBo,Boolean.TRUE);
        } catch (IOException e) {
            throw FException.of("文件保存失败",502,e);
        }
    }

    /**
     * 文件下载
     * @param response 原生响应体
     * @param fileMetaBo 文件记录实例
     */
    public static void downloadFile(HttpServletResponse response, FileMetaBo fileMetaBo) {
        if (Objects.isNull(fileMetaBo)){
            throw FException.of("此文件记录不存在或已失效",401);
        }
        File file = new File(fileMetaBo.getSavePath());
        if (!file.exists()){
            throw FException.of("文件资源未找到，下载失败",401);
        }
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", "attachment;fileName=" +  fileMetaBo.getUuid()+ fileMetaBo.getFileType());
        try (
                FileInputStream fis = new FileInputStream(file);
                BufferedInputStream bis = new BufferedInputStream(fis);
                OutputStream opt= response.getOutputStream()){
            byte[] buffer = new byte[1024 * 4];
            int i = bis.read(buffer);
            while (i!=-1){
                opt.write(buffer,0,i);
                i = bis.read(buffer);
            }
        }catch (Exception e){
            throw FException.of("下载服务异常",e);
        }
    }

    private static FileMetaBo readFileToEntity(MultipartFile multipartFile) {
        FileMetaBo fileMetaBo = new FileMetaBo();
        fileMetaBo.setUuid(UuidUitl.createUuidWithoutDelimiter());
        fileMetaBo.setFileType(multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().indexOf(".")));
        fileMetaBo.setOldName(multipartFile.getOriginalFilename().substring(0, multipartFile.getOriginalFilename().indexOf(".")));
        fileMetaBo.setSize(multipartFile.getSize());
        fileMetaBo.setSavePath(FileUtil.generateAbsPathWithClassPath()+fileMetaBo.getUuid()+fileMetaBo.getFileType());
        return fileMetaBo;
    }
}
